package xarray

import (
	"fmt"
	"strings"
)

type Array[T comparable] struct {
	Values []T
}

func New[T comparable](v ...T) *Array[T] {
	arr := &Array[T]{
		Values: make([]T, 0),
	}
	if len(v) > 0 {
		arr.SetValues(v)
	}
	return arr
}

func (arr *Array[T]) SetValues(values []T) {
	arr.Values = values
}

func (arr *Array[T]) Value() []T {
	return arr.Values
}

func (arr *Array[T]) Len() int {
	return len(arr.Values)
}

func (arr *Array[T]) Push(v T) int {
	arr.Values = append(arr.Values, v)
	return arr.Len()
}

func (arr *Array[T]) Pop() (T, bool) {
	var zero T
	l := arr.Len()
	if l == 0 {
		return zero, false
	}
	top := arr.Values[l-1]
	arr.Values = arr.Values[:l-1]
	return top, true
}

func (arr *Array[T]) IndexOf(value T) int {
	for index, v := range arr.Values {
		if value == v {
			return index
		}
	}

	return -1
}

func (arr *Array[T]) Map(f func(val T) (T, bool)) []T {
	result := make([]T, 0)
	for i := 0; i < arr.Len(); i++ {
		if v, ok := f(arr.Values[i]); ok {
			result = append(result, v)
		}
	}

	return result
}

func (arr *Array[T]) Find(f func(val T) bool) (T, bool) {
	var zero T
	for i := 0; i < arr.Len(); i++ {
		if f(arr.Values[i]) {
			return arr.Values[i], true
		}
	}

	return zero, false
}

func (arr *Array[T]) Unique() []T {
	m := make(map[T]struct{})
	r := make([]T, 0)
	for i := 0; i < arr.Len(); i++ {
		if _, ok := m[arr.Values[i]]; !ok {
			r = append(r, arr.Values[i])
			m[arr.Values[i]] = struct{}{}
		}
	}

	return r
}

// Empty
// 判断是否为空数组，这里的空数组指的是数组元素个数为0或元素不为0但是元素的值都是零值的数组
func (arr *Array[T]) Empty() bool {
	if arr.Len() == 0 {
		return true
	}
	var zero T
	for i := 0; i < arr.Len(); i++ {
		if arr.Values[i] != zero {
			return false
		}
	}

	return true
}

func (arr *Array[T]) Reverse() {
	length := arr.Len()
	if length == 0 {
		return
	}
	var temp T
	for i := 0; i < length/2; i++ {
		temp = arr.Values[length-1-i]
		arr.Values[length-1-i] = arr.Values[i]
		arr.Values[i] = temp
	}
}

func (arr *Array[T]) Join(sep string) string {
	str := ""
	for _, v := range arr.Values {
		str = str + fmt.Sprintf("%v%s", v, sep)
	}

	return strings.TrimRight(str, sep)
}

func IndexOf[T comparable](array []T, value T) int {
	arr := &Array[T]{}
	arr.SetValues(array)
	return arr.IndexOf(value)
}

func Empty[T comparable](array []T) bool {
	arr := &Array[T]{}
	arr.SetValues(array)
	return arr.Empty()
}

func Unique[T comparable](array []T) []T {
	arr := &Array[T]{}
	arr.SetValues(array)
	return arr.Unique()
}

func SplitSlice[T any](slice []T, chunkSize int) [][]T {
	if chunkSize <= 0 {
		return nil // 处理无效的chunkSize
	}

	var chunks [][]T
	for i := 0; i < len(slice); i += chunkSize {
		end := i + chunkSize
		if end > len(slice) {
			end = len(slice)
		}
		chunks = append(chunks, slice[i:end])
	}
	return chunks
}
